#include "talkwindow.h"

#include "talkwindow/TalkUserInfo.hpp"
#include "ui_talkwindow.h"

#include <Application.h>
#include <QDateTime>
#include <QFileDialog>
#include <QToolTip>
#include <data/File.pb.h>
#include <data/Message.pb.h>
#include <data/UserInfo.pb.h>
#include <openssl/OpenSSL.h>
#include <packge/packge.h>

using namespace proto;
#include <CommonUtils.h>
// #include <uploadfile/uploadfileform.h>

TalkWindow::TalkWindow(QWidget* parent)
    : QWidget(parent),
      ui(new Ui::TalkWindow) {
    ui->setupUi(this);
    // CommonUtils::loadStyleSheet(this, "talkwindow");
    init();

    ui->bodySplitter->setStretchFactor(0, 10);
    ui->bodySplitter->setStretchFactor(1, 1);
}

TalkWindow::~TalkWindow() {
    delete ui;
}

void TalkWindow::setTitle(QString title) {
    ui->labelTitle->setText(title);
}

void TalkWindow::setInfo(const data::FriendInfo& userInfo) {
    this->userInfo = userInfo;
    userId         = userInfo.userid().c_str();
    type           = PTOP;
    ui->widget_list->close();
    TalkUserInfo info{
        userInfo.userid().c_str(),
        userInfo.name().c_str(),
        userInfo.headshot().c_str(),
    };
    ui->messageWidget->setUserInfo(info);
}

void TalkWindow::setInfo(const data::ChatRoomInfo& roomInfo) {
    this->roomInfo = roomInfo;
    userId         = roomInfo.roomid().c_str();
    type           = GROUP;
    // ui->widget_list->close();
    TalkUserInfo info{
        roomInfo.roomid().c_str(),
        roomInfo.name().c_str(),
        roomInfo.headshot().c_str(),
    };
    ui->messageWidget->setUserInfo(info);
}

void TalkWindow::init() {
    ui->widget_title->hide();
    initEmotionWindow();
    initMessageWebView();

    connect(ui->titlebar, &TitleBar::signalButtonCloseClicked, this, &TalkWindow::onButtonCloseClicked);
    connect(ui->titlebar, &TitleBar::signalButtonMaxClicked, this, &TalkWindow::onButtonMaxClicked);
    connect(ui->titlebar, &TitleBar::signalButtonMinClicked, this, &TalkWindow::onButtonMinClicked);
    connect(ui->titlebar, &TitleBar::signalButtonRestoreClicked, this, &TalkWindow::onButtonRestoreClicked);

    connect(ui->sendBtn, &QPushButton::clicked, this, &TalkWindow::onSendButtonClicked);

    connect(ui->fileopenBtn, &QPushButton::clicked, this, &TalkWindow::onFileopenBtnClicked);
    connect(ui->imgopenBtn, &QPushButton::clicked, this, &TalkWindow::onImgopenBtnClicked);
    // connect(Application::getInstance(), &Application::signalFile, this, &TalkWindow::onUploadFile);
    // connect(Application::getInstance(), &Application::signalUploadFileSchedule, this, &TalkWindow::onUploadFileSchedule);
}

void TalkWindow::initEmotionWindow() {
    emotionWindow = new EmotionWindow();
    emotionWindow->hide();

    this->installEventFilter(emotionWindow);

    connect(emotionWindow, &EmotionWindow::signalEmotionItemClicked, this, &TalkWindow::onEmotionItemClicked);
    connect(ui->emotionBtn, &QPushButton::clicked, [this](bool) {
        emotionWindow->setVisible(!emotionWindow->isVisible());
        // QPoint emotionPoint = this->mapToGlobal(QPoint(0, 0));  // 将当前控件的相对位置转换成屏幕的绝对位置
        if (emotionWindow->isVisible())
            emotionWindow->activateWindow();
        auto emotionPoint = (cursor().pos());
        emotionPoint.setX(emotionPoint.x() - 20);
        emotionPoint.setY(emotionPoint.y() - emotionWindow->height() - 10);
        emotionWindow->move(emotionPoint);
    });
}

void TalkWindow::initMessageWebView() {
    connect(ui->messageWidget, &MsgWebView::loadFinished, this, &TalkWindow::onWebViewLoadFinishd);
}

void TalkWindow::onWebViewLoadFinishd() {
    isMessageWebViewLoadFinishd = true;
}

void TalkWindow::onButtonCloseClicked() {
    emit signalButtonCloseClicked();
}

void TalkWindow::onButtonMaxClicked() {
    emit signalButtonMaxClicked();
}

void TalkWindow::onButtonMinClicked() {
    emit signalButtonMinClicked();
}

void TalkWindow::onButtonRestoreClicked() {
    emit signalButtonRestoreClicked();
}

void TalkWindow::onWindowRestore() {
    ui->titlebar->showButtonMax();
}

void TalkWindow::onNewMessage(std::shared_ptr<::proto::data::Message> msg) {
    QString id = "";
    if (type == GROUP) {
        // 群聊时，如果是自己发的数据就不用显示到页面上了
        if (msg->from_user_id() == Application::Myself().userid()) {
            return;
        }
        id = msg->to_user_id().c_str();
    }
    else {
        id = msg->from_user_id().c_str();
    }

    if (id == userId) {
        messages.push_back(msg);
        if (msg->text() != "")
            ui->messageWidget->recvMsg(msg->text().c_str());
        // if (!msg->files.empty()) {
        //     packet::file::FileInfo info;
        //     for (auto&& i : msg->files) {
        //         info.url = i;
        //         ui->messageWidget->recvFile(info);
        //     }
        // }
        emit signalNewMessage(msg);
    }
}

void TalkWindow::onEmotionItemClicked(int emotionNum) {
    ui->textEdit->setFocus();
    ui->textEdit->addEmotionUrl(emotionNum);
}

// void TalkWindow::onUploadFile(packet::file::FileInfo info, int code, QString message) {
//     if (m_uploeadFiles.find(info.name().c_str()) != m_uploeadFiles.end()) {
//         m_uploeadFiles.erase(info.name().c_str());

//         auto msg        = std::make_shared<::proto::data::Message>();
//         msg->type       = type == PTOP ? ::proto::data::Message::PTOP : ::proto::data::Message::GROUP;
//         msg->from_user_id() = Application::Myself().userid().c_str();
//         msg->to_user_id().c_str()   = userId;
//         msg->time       = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");

//         msg->text += info.url;
//         msg->files.push_back(info.url);
//         ui->messageWidget->appendFile(info);
//         Application::getInstance()->Send(*msg);

//         messages.push_back(msg);
//         emit signalNewMessage(msg);
//     }
// }

// void TalkWindow::uploadFile(QString path) {
//     packet::file::FilePacket pack;
//     auto&                    info = pack.info;

//     QFile file(path);
//     if (file.open(QIODevice::ReadOnly)) {
//         info.name().c_str() = path.mid(path.lastIndexOf('/') + 1);
//         info.type = path.mid(path.lastIndexOf('.'));
//         info.url  = "";

//         auto data      = path.toLocal8Bit();
//         info.hashcode  = openssl::GetFileHash(std::string(data.data(), data.size()), openssl::Algorithm::MD5).c_str();
//         info.fileSize  = file.size();
//         info.packCount = info.fileSize / pack.MaxPacketSize + 1;
//         info.packId    = 0;

//         m_uploeadFiles.insert(info.hashcode);

//         size_t sendSize = 0;
//         while (sendSize < info.fileSize) {
//             int read_size    = std::min(info.fileSize - sendSize, (size_t)pack.MaxPacketSize);
//             pack.fileContent = data = file.read(read_size);
//             Application::getInstance()->Send(pack);

//             qDebug() << "SendFile:"
//                      << "[" << info.name().c_str() << "] "
//                      << "(" << info.packCount << "/" << info.packId + 1 << ")";

//             sendSize += read_size;
//             ++info.packId;
//         }
//     }
// }

void TalkWindow::onFileopenBtnClicked() {
    // static QFileDialog* dialog = nullptr;
    // if (dialog == nullptr) {
    //     dialog = new QFileDialog(this);
    //     dialog->setFileMode(QFileDialog::AnyFile);
    //     dialog->setNameFilter("所有文件 (*)");
    //     dialog->setViewMode(QFileDialog::Detail);
    //     dialog->setOptions(QFileDialog::DontUseNativeDialog);
    // }
    // if (dialog->exec()) {
    //     QStringList selectedFiles = dialog->selectedFiles();
    //     // 处理选择的文件
    //     ui->textEdit->setFocus();
    //     for (auto&& i : selectedFiles) {
    //         ui->textEdit->addFileUrl(i);
    //         m_talk_files.push(i);
    //     }
    // }
    QString filename = QFileDialog::getOpenFileName();
    // 处理选择的文件
    ui->textEdit->setFocus();
    ui->textEdit->addFileUrl(filename);
    m_talk_files.push(filename);
}

void TalkWindow::onImgopenBtnClicked() {
    static QFileDialog* dialog = nullptr;
    if (dialog == nullptr) {
        dialog = new QFileDialog(this);
        dialog->setFileMode(QFileDialog::AnyFile);
        dialog->setNameFilter("图像文件 (*.png *.img *.jpg *.gif);;所有文件 (*)");
        dialog->setViewMode(QFileDialog::Detail);
        dialog->setOptions(QFileDialog::DontUseNativeDialog);
    }
    if (dialog->exec()) {
        QStringList selectedFiles = dialog->selectedFiles();
        // 处理选择的文件
        ui->textEdit->setFocus();
        for (auto&& i : selectedFiles) {
            ui->textEdit->addImageUrl(i);
        }
    }
}

void TalkWindow::onUploadFileSchedule(QString fileName, size_t fileSize, size_t schedule) {
    if (m_uploeadFiles.find(fileName) != m_uploeadFiles.end()) {
        qDebug() << "upload :" << fileName << " [ " << fileSize << "/" << schedule << "]";
    }
}

QString TalkWindow::parseHtml(const QString& htmlText) {
    QDomDocument doc;
    QString      text;

    qDebug() << "htmlText:" << htmlText;
    if (doc.setContent(htmlText)) {
        QDomElement  root       = doc.documentElement();
        QDomNodeList paragraphs = root.elementsByTagName("p");

        for (int i = 0; i < paragraphs.size(); ++i) {
            if (i != 0) {
                text += "<br>";
            }
            QDomElement paragraph = paragraphs.at(i).toElement();

            QDomNodeList childNodes = paragraph.childNodes();
            for (int j = 0; j < childNodes.size(); ++j) {
                QDomNode childNode = childNodes.at(j);
                if (childNode.isElement()) {
                    QDomElement childElement = childNode.toElement();
                    if (childElement.tagName() == "img") {
                        QString src    = childElement.attribute("src");
                        bool    isEmoj = src.contains("emojiqq");
                        // Extract the filename from the src attribute
                        int slashIndex = src.lastIndexOf('/');
                        if (slashIndex != -1) {
                            if (isEmoj) {
                                QString fileName = src.mid(slashIndex + 1);
                                text += "<emoj>" + fileName + "</emoj>";
                            }
                            else {
                                text += "<img src=\"" + src + "\">";
                            }
                        }
                    }
                    if (childElement.tagName() == "span") {
                        text += childElement.text();
                    }
                }
                else if (childNode.isText()) {
                    text += childNode.toText().data();
                }
            }
        }
    }
    return text;
}

void TalkWindow::onSendButtonClicked() {
    if (!m_talk_files.empty()) {
        while (!m_talk_files.empty()) {
            auto i = m_talk_files.front();
            m_talk_files.pop();
            auto filename = i.mid(i.lastIndexOf('/') + 1);

            m_uploeadFiles.insert(filename);
            // uploadFile(i);
            // UploadFileForm form;
            // form.setFileName(filename);
            // // form->moveToThread(Application::getInstance()->getSocketThread());
            // Application::getInstance()->UploadFile(i);
            // form.exec();
        }
    }
    if (ui->textEdit->toPlainText().isEmpty()) {
        auto p = cursor().pos();

        QToolTip::showText(
            (QPoint(p.x() - 90, p.y() - 50)),
            QString("发送的内容不能为空"),
            this,
            QRect(0, 0, 120, 100), 2000);

        return;
    }

    QString html = ui->textEdit->document()->toHtml();
    ui->textEdit->clear();
    ui->textEdit->deleteAllEmotionImage();

    auto msg = std::make_shared<::proto::data::Message>();
    msg->set_type(type == PTOP ? ::proto::data::Message::PTOP : ::proto::data::Message::GROUP);
    msg->set_from_user_id(Application::Myself().userid());
    msg->set_to_user_id(userId.toStdString());
    msg->set_time(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss").toStdString());

    msg->set_text(parseHtml(html).toStdString());

    ui->messageWidget->appendMsg(msg->text().c_str());
    Application::instance()->message(*msg);

    messages.push_back(msg);
    emit signalNewMessage(msg);
}